<!DOCTYPE html>
<html lang="en">

<head>
  <title>SD Editor</title>
  <style type="text/css" media="screen">
    .contextMenu {
      z-index: 300;
      position: absolute;
      left: 5px;
      border: 1px solid #444;
      background-color: #F5F5F5;
      display: none;
      box-shadow: 0 0 10px rgba(0, 0, 0, .4);
      font-size: 12px;
      font-family: sans-serif;
      font-weight: bold;
    }

    .contextMenu ul {
      list-style: none;
      top: 0;
      left: 0;
      margin: 0;
      padding: 0;
    }

    .contextMenu li {
      position: relative;
      min-width: 60px;
      cursor: pointer;
    }

    .contextMenu span {
      color: #444;
      display: inline-block;
      padding: 6px;
    }

    .contextMenu li:hover {
      background: #444;
    }

    .contextMenu li:hover span {
      color: #EEE;
    }

    .css-treeview ul,
    .css-treeview li {
      padding: 0;
      margin: 0;
      list-style: none;
    }

    .css-treeview input {
      position: absolute;
      opacity: 0;
    }

    .css-treeview {
      font: normal 11px Verdana, Arial, Sans-serif;
      -moz-user-select: none;
      -webkit-user-select: none;
      user-select: none;
    }

    .css-treeview span {
      color: #00f;
      cursor: pointer;
    }

    .css-treeview span:hover {
      text-decoration: underline;
    }

    .css-treeview input+label+ul {
      margin: 0 0 0 22px;
    }

    .css-treeview input~ul {
      display: none;
    }

    .css-treeview label,
    .css-treeview label::before {
      cursor: pointer;
    }

    .css-treeview input:disabled+label {
      cursor: default;
      opacity: .6;
    }

    .css-treeview input:checked:not(:disabled)~ul {
      display: block;
    }

    .css-treeview label,
    .css-treeview label::before {
      background: url("") no-repeat;
    }

    .css-treeview label,
    .css-treeview span,
    .css-treeview label::before {
      display: inline-block;
      height: 16px;
      line-height: 16px;
      vertical-align: middle;
    }

    .css-treeview label {
      background-position: 18px 0;
    }

    .css-treeview label::before {
      content: "";
      width: 16px;
      margin: 0 22px 0 0;
      vertical-align: middle;
      background-position: 0 -32px;
    }

    .css-treeview input:checked+label::before {
      background-position: 0 -16px;
    }

    /* webkit adjacent element selector bugfix */
    @media screen and (-webkit-min-device-pixel-ratio:0) {
      .css-treeview {
        -webkit-animation: webkit-adjacent-element-selector-bugfix infinite 1s;
      }

      @-webkit-keyframes webkit-adjacent-element-selector-bugfix {
        from {
          padding: 0;
        }

        to {
          padding: 0;
        }
      }
    }

    #uploader {
      position: absolute;
      top: 0;
      right: 0;
      left: 0;
      height: 28px;
      line-height: 24px;
      padding-left: 10px;
      background-color: #444;
      color: #EEE;
    }

    #tree {
      position: absolute;
      top: 28px;
      bottom: 0;
      left: 0;
      width: 500px;
      padding: 8px;
    }

    #editor,
    #preview {
      position: absolute;
      top: 28px;
      right: 0;
      bottom: 0;
      left: 200px;
    }

    #preview {
      background-color: #EEE;
      padding: 5px;
    }
  </style>
  <script>
    function createFileUploader(element, tree, editor) {
      var xmlHttp;
      var input = document.createElement("input");
      input.type = "file";
      input.multiple = false;
      input.name = "data";
      document.getElementById(element).appendChild(input);
      var path = document.createElement("input");
      path.id = "upload-path";
      path.type = "text";
      path.name = "path";
      path.defaultValue = "/";
      document.getElementById(element).appendChild(path);
      var button = document.createElement("button");
      button.innerHTML = 'Upload';
      document.getElementById(element).appendChild(button);
      var mkdir = document.createElement("button");
      mkdir.innerHTML = 'MkDir';
      document.getElementById(element).appendChild(mkdir);
      var mkfile = document.createElement("button");
      mkfile.innerHTML = 'MkFile';
      document.getElementById(element).appendChild(mkfile);
      var clean = document.createElement("button");
      clean.innerHTML = 'Clean Srceen';
      document.getElementById(element).appendChild(clean);

      function httpPostProcessRequest() {
        if (xmlHttp.readyState == 4) {
          if (xmlHttp.status != 200) alert("ERROR[" + xmlHttp.status + "]: " + xmlHttp.responseText);
          else {
            tree.refreshPath(path.value);
          }
        }
      }
      function createPath(p) {
        xmlHttp = new XMLHttpRequest();
        xmlHttp.onreadystatechange = httpPostProcessRequest;
        var formData = new FormData();
        formData.append("path", p);
        xmlHttp.open("PUT", "/edit");
        xmlHttp.send(formData);
      }

      mkfile.onclick = function (e) {
        if (path.value.indexOf(".") === -1) return;
        createPath(path.value);
        editor.loadUrl(path.value);
      };
      mkdir.onclick = function (e) {
        if (path.value.length < 2) return;
        var dir = path.value
        if (dir.indexOf(".") !== -1) {
          if (dir.lastIndexOf("/") === 0) return;
          dir = dir.substring(0, dir.lastIndexOf("/"));
        }
        createPath(dir);
      };
      button.onclick = function (e) {
        if (input.files.length === 0) {
          return;
        }
        xmlHttp = new XMLHttpRequest();
        xmlHttp.onreadystatechange = httpPostProcessRequest;
        var formData = new FormData();
        formData.append("data", input.files[0], path.value);
        xmlHttp.open("POST", "/edit");
        xmlHttp.send(formData);

      }
      input.onchange = function (e) {
        if (input.files.length === 0) return;
        var filename = input.files[0].name;
        var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
        var name = /(.*)\.[^.]+$/.exec(filename)[1];
        if (typeof name !== undefined) {
          if (name.length > 8) name = name.substring(0, 8);
          filename = name;
        }
        if (typeof ext !== undefined) {
          if (ext === "html") ext = "htm";
          else if (ext === "jpeg") ext = "jpg";
          filename = filename + "." + ext;
        }
        if (path.value === "/" || path.value.lastIndexOf("/") === 0) {
          path.value = "/" + filename;
        } else {
          path.value = path.value.substring(0, path.value.lastIndexOf("/") + 1) + filename;
        }
      }

      clean.onclick = function (e) {

        xmlHttp = new XMLHttpRequest();
        xmlHttp.onreadystatechange = httpPostProcessRequest;
        // var formData = new FormData();
        // formData.append("data", input.files[0], path.value);
        xmlHttp.open("POST", "/clean");
        xmlHttp.send(null);

      }
    }

    function createTree(element, editor) {
      var xmlHttp;
      var preview = document.getElementById("preview");
      var treeRoot = document.createElement("div");
      treeRoot.className = "css-treeview";
      document.getElementById(element).appendChild(treeRoot);

      function loadDownload(path) {
        document.getElementById('download-frame').src = path + "?download=true";
      }

      function loadPreview(path) {
        document.getElementById("editor").style.display = "none";
        preview.style.display = "block";
        preview.innerHTML = '<img src="' + path + '" style="max-width:100%; max-height:100%; margin:auto; display:block;" />';
      }

      //  function getputCb() {
      //     if (xmlHttp.readyState == 4) {
      //       //clear loading
      //       if (xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
      //     }
      //   }
      // }
      function sendDisplay(path) {
        xmlHttp = new XMLHttpRequest();
        // xmlHttp.onreadystatechange = getputCb;
        var formData = new FormData();
        formData.append("path", path);
        xmlHttp.open("POST", "/show");
        xmlHttp.send(formData);
        console.log(path);
      }

      function fillFolderMenu(el, path) {
        var list = document.createElement("ul");
        el.appendChild(list);
        var action = document.createElement("li");
        list.appendChild(action);
        var isChecked = document.getElementById(path).checked;
        var expnd = document.createElement("li");
        list.appendChild(expnd);
        if (isChecked) {
          expnd.innerHTML = "<span>Collapse</span>";
          expnd.onclick = function (e) {
            document.getElementById(path).checked = false;
            if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
          };
          var refrsh = document.createElement("li");
          list.appendChild(refrsh);
          refrsh.innerHTML = "<span>Refresh</span>";
          refrsh.onclick = function (e) {
            var leaf = document.getElementById(path).parentNode;
            if (leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
            httpGet(leaf, path);
            if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
          };
        } else {
          expnd.innerHTML = "<span>Expand</span>";
          expnd.onclick = function (e) {
            document.getElementById(path).checked = true;
            var leaf = document.getElementById(path).parentNode;
            if (leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
            httpGet(leaf, path);
            if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
          };
        }
        var upload = document.createElement("li");
        list.appendChild(upload);
        upload.innerHTML = "<span>Upload</span>";
        upload.onclick = function (e) {
          var pathEl = document.getElementById("upload-path");
          if (pathEl) {
            var subPath = pathEl.value;
            if (subPath.lastIndexOf("/") < 1) pathEl.value = path + subPath;
            else pathEl.value = path.substring(subPath.lastIndexOf("/")) + subPath;
          }
          if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
        };
        var delFile = document.createElement("li");
        list.appendChild(delFile);
        delFile.innerHTML = "<span>Delete</span>";
        delFile.onclick = function (e) {
          httpDelete(path);
          if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
        };
      }

      function fillFileMenu(el, path) {
        var list = document.createElement("ul");
        el.appendChild(list);
        var action = document.createElement("li");
        list.appendChild(action);
        var show = document.createElement("li");
        list.appendChild(show);
        if (isTextFile(path)) {
          action.innerHTML = "<span>Edit</span>";
          action.onclick = function (e) {
            editor.loadUrl(path);
            if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
          };
        } else if (isImageFile(path)) {
          action.innerHTML = "<span>Preview</span>";
          action.onclick = function (e) {
            loadPreview(path);
            if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
          };
          show.innerHTML = "<span>Display on EDP</span>";
          show.onclick = function (e) {
            // loadPreview(path);
            sendDisplay(path)
            if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
          };
        }
        var download = document.createElement("li");
        list.appendChild(download);
        download.innerHTML = "<span>Download</span>";
        download.onclick = function (e) {
          loadDownload(path);
          if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
        };
        var delFile = document.createElement("li");
        list.appendChild(delFile);
        delFile.innerHTML = "<span>Delete</span>";
        delFile.onclick = function (e) {
          httpDelete(path);
          if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(el);
        };
      }

      function showContextMenu(e, path, isfile) {
        var divContext = document.createElement("div");
        var scrollTop = document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop;
        var scrollLeft = document.body.scrollLeft ? document.body.scrollLeft : document.documentElement.scrollLeft;
        var left = e.clientX + scrollLeft;
        var top = e.clientY + scrollTop;
        divContext.className = 'contextMenu';
        divContext.style.display = 'block';
        divContext.style.left = left + 'px';
        divContext.style.top = top + 'px';
        if (isfile) fillFileMenu(divContext, path);
        else fillFolderMenu(divContext, path);
        document.body.appendChild(divContext);
        var width = divContext.offsetWidth;
        var height = divContext.offsetHeight;
        divContext.onmouseout = function (e) {
          if (e.clientX < left || e.clientX > (left + width) || e.clientY < top || e.clientY > (top + height)) {
            if (document.body.getElementsByClassName('contextMenu').length > 0) document.body.removeChild(divContext);
          }
        };
      }

      function createTreeLeaf(path, name, size) {
        var leaf = document.createElement("li");
        leaf.id = name.toLowerCase();
        var label = document.createElement("span");
        label.textContent = name.toLowerCase();
        leaf.appendChild(label);
        leaf.onclick = function (e) {
          if (isTextFile(leaf.id)) {
            editor.loadUrl(leaf.id);
          } else if (isImageFile(leaf.id)) {
            loadPreview(leaf.id);
          }
        };
        leaf.oncontextmenu = function (e) {
          e.preventDefault();
          e.stopPropagation();
          showContextMenu(e, leaf.id, true);
        };
        return leaf;
      }

      function createTreeBranch(path, name, disabled) {
        var leaf = document.createElement("li");
        var check = document.createElement("input");
        check.type = "checkbox";
        check.id = name.toLowerCase();
        if (typeof disabled !== "undefined" && disabled) check.disabled = "disabled";
        leaf.appendChild(check);
        var label = document.createElement("label");
        label.for = check.id;
        label.textContent = name.toLowerCase();
        leaf.appendChild(label);
        check.onchange = function (e) {
          if (check.checked) {
            if (leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
            httpGet(leaf, check.id);
          }
        };
        label.onclick = function (e) {
          if (!check.checked) {
            check.checked = true;
            if (leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
            httpGet(leaf, check.id);
          } else {
            check.checked = false;
          }
        };
        leaf.oncontextmenu = function (e) {
          e.preventDefault();
          e.stopPropagation();
          showContextMenu(e, check.id, false);
        }
        return leaf;
      }

      function addList(parent, path, items) {
        var list = document.createElement("ul");
        parent.appendChild(list);
        var ll = items.length;
        for (var i = 0; i < ll; i++) {
          var item = items[i];
          var itemEl;
          if (item.type === "file") {
            itemEl = createTreeLeaf(path, item.name, item.size);
          } else {
            itemEl = createTreeBranch(path, item.name);
          }
          list.appendChild(itemEl);
        }

      }

      function isTextFile(path) {
        var ext = /(?:\.([^.]+))?$/.exec(path)[1];
        if (typeof ext !== undefined) {
          switch (ext) {
            case "txt":
            case "htm":
            case "html":
            case "js":
            case "json":
            case "c":
            case "h":
            case "cpp":
            case "css":
            case "xml":
              return true;
          }
        }
        return false;
      }

      function isImageFile(path) {
        var ext = /(?:\.([^.]+))?$/.exec(path)[1];
        if (typeof ext !== undefined) {
          switch (ext) {
            case "png":
            case "jpg":
            case "gif":
            case "ico":
              return true;
          }
        }
        return false;
      }

      this.refreshPath = function (path) {
        if (path.lastIndexOf('/') < 1) {
          path = '/';
          treeRoot.removeChild(treeRoot.childNodes[0]);
          httpGet(treeRoot, "/");
        } else {
          path = path.substring(0, path.lastIndexOf('/'));
          var leaf = document.getElementById(path).parentNode;
          if (leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
          httpGet(leaf, path);
        }
      };

      function delCb(path) {
        return function () {
          if (xmlHttp.readyState == 4) {
            if (xmlHttp.status != 200) {
              alert("ERROR[" + xmlHttp.status + "]: " + xmlHttp.responseText);
            } else {
              if (path.lastIndexOf('/') < 1) {
                path = '/';
                treeRoot.removeChild(treeRoot.childNodes[0]);
                httpGet(treeRoot, "/");
              } else {
                path = path.substring(0, path.lastIndexOf('/'));
                var leaf = document.getElementById(path).parentNode;
                if (leaf.childNodes.length == 3) leaf.removeChild(leaf.childNodes[2]);
                httpGet(leaf, path);
              }
            }
          }
        }
      }

      function httpDelete(filename) {
        xmlHttp = new XMLHttpRequest();
        xmlHttp.onreadystatechange = delCb(filename);
        var formData = new FormData();
        formData.append("path", filename);
        xmlHttp.open("DELETE", "/edit");
        xmlHttp.send(formData);
      }

      function getCb(parent, path) {
        return function () {
          if (xmlHttp.readyState == 4) {
            //clear loading
            if (xmlHttp.status == 200) addList(parent, path, JSON.parse(xmlHttp.responseText));
          }
        }
      }

      function httpGet(parent, path) {
        xmlHttp = new XMLHttpRequest(parent, path);
        xmlHttp.onreadystatechange = getCb(parent, path);
        xmlHttp.open("GET", "/list?dir=" + path, true);
        xmlHttp.send(null);
        //start loading
      }

      httpGet(treeRoot, "/");
      return this;
    }

    function createEditor(element, file, lang, theme, type) {
      function getLangFromFilename(filename) {
        var lang = "plain";
        var ext = /(?:\.([^.]+))?$/.exec(filename)[1];
        if (typeof ext !== undefined) {
          switch (ext) {
            case "txt": lang = "plain"; break;
            case "htm": lang = "html"; break;
            case "js": lang = "javascript"; break;
            case "c": lang = "c_cpp"; break;
            case "cpp": lang = "c_cpp"; break;
            case "css":
            case "scss":
            case "php":
            case "html":
            case "json":
            case "xml":
              lang = ext;
          }
        }
        return lang;
      }

      if (typeof file === "undefined") file = "/index.htm";

      if (typeof lang === "undefined") {
        lang = getLangFromFilename(file);
      }

      if (typeof theme === "undefined") theme = "textmate";

      if (typeof type === "undefined") {
        type = "text/" + lang;
        if (lang === "c_cpp") type = "text/plain";
      }

      var xmlHttp = null;
      var editor = ace.edit(element);

      //post
      function httpPostProcessRequest() {
        if (xmlHttp.readyState == 4) {
          if (xmlHttp.status != 200) alert("ERROR[" + xmlHttp.status + "]: " + xmlHttp.responseText);
        }
      }
      function httpPost(filename, data, type) {
        xmlHttp = new XMLHttpRequest();
        xmlHttp.onreadystatechange = httpPostProcessRequest;
        var formData = new FormData();
        formData.append("data", new Blob([data], { type: type }), filename);
        xmlHttp.open("POST", "/edit");
        xmlHttp.send(formData);
      }
      //get
      function httpGetProcessRequest() {
        if (xmlHttp.readyState == 4) {
          document.getElementById("preview").style.display = "none";
          document.getElementById("editor").style.display = "block";
          if (xmlHttp.status == 200) editor.setValue(xmlHttp.responseText);
          else editor.setValue("");
          editor.clearSelection();
        }
      }
      function httpGet(theUrl) {
        xmlHttp = new XMLHttpRequest();
        xmlHttp.onreadystatechange = httpGetProcessRequest;
        xmlHttp.open("GET", theUrl, true);
        xmlHttp.send(null);
      }

      if (lang !== "plain") editor.getSession().setMode("ace/mode/" + lang);
      editor.setTheme("ace/theme/" + theme);
      editor.$blockScrolling = Infinity;
      editor.getSession().setUseSoftTabs(true);
      editor.getSession().setTabSize(2);
      editor.setHighlightActiveLine(true);
      editor.setShowPrintMargin(false);
      editor.commands.addCommand({
        name: 'saveCommand',
        bindKey: { win: 'Ctrl-S', mac: 'Command-S' },
        exec: function (editor) {
          httpPost(file, editor.getValue() + "", type);
        },
        readOnly: false
      });
      editor.commands.addCommand({
        name: 'undoCommand',
        bindKey: { win: 'Ctrl-Z', mac: 'Command-Z' },
        exec: function (editor) {
          editor.getSession().getUndoManager().undo(false);
        },
        readOnly: false
      });
      editor.commands.addCommand({
        name: 'redoCommand',
        bindKey: { win: 'Ctrl-Shift-Z', mac: 'Command-Shift-Z' },
        exec: function (editor) {
          editor.getSession().getUndoManager().redo(false);
        },
        readOnly: false
      });
      httpGet(file);
      editor.loadUrl = function (filename) {
        file = filename;
        lang = getLangFromFilename(file);
        type = "text/" + lang;
        if (lang !== "plain") editor.getSession().setMode("ace/mode/" + lang);
        httpGet(file);
      }
      return editor;
    }
    function onBodyLoad() {
      var vars = {};
      var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (m, key, value) { vars[key] = value; });
      var editor = createEditor("editor", vars.file, vars.lang, vars.theme);
      var tree = createTree("tree", editor);
      createFileUploader("uploader", tree, editor);
    };
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.1.9/ace.js" type="text/javascript" charset="utf-8"></script>
</head>

<body onload="onBodyLoad();">
  <div id="uploader"></div>
  <div id="tree"></div>
  <div id="editor"></div>
  <div id="preview" style="display:none;"></div>
  <iframe id=download-frame style='display:none;'></iframe>
</body>

</html>